package com.corpgovernment.organization.service.impl;

import com.corpgovernment.api.organization.bo.SyncOrgEmployeeReq;
import com.corpgovernment.common.common.CorpBusinessException;
import com.corpgovernment.organization.constant.OrganizationResponseCodeEnum;
import com.corpgovernment.organization.dataloader.db.MbOrgInfoLoader;
import com.corpgovernment.organization.entity.db.MbOrgInfo;
import com.corpgovernment.organization.entity.db.MbPostInfo;
import com.corpgovernment.organization.enumm.OrgTypeEnum;
import com.corpgovernment.organization.enumm.PositionOperationEnum;
import com.corpgovernment.organization.model.SyncPositionInfoModel;
import com.corpgovernment.organization.service.IOrganizationInfoService;
import com.corpgovernment.organization.service.IPostService;
import com.corpgovernment.organization.service.PositionInfoService;
import com.ctrip.corp.obt.generic.utils.CollectionUtils;
import com.ctrip.corp.obt.generic.utils.Conditional;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author zl.cui
 * @date 2023/10/7
 */
@Component
@Slf4j
public class PositionInfoServiceImpl implements PositionInfoService {
    @Autowired
    private IPostService postService;
    @Autowired
    private MbOrgInfoLoader mbOrgInfoLoader;
    @Autowired
    private IOrganizationInfoService organizationInfoService;
    /**
     * 最大递归次数
     */
    private final static int MAX_CALL_COUNT = 50;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void syncPositionInfo(List<SyncPositionInfoModel> syncPositionList, String corpCode) {
        Map<Integer, List<SyncPositionInfoModel>> positionMap = syncPositionList.stream().collect(Collectors.groupingBy(SyncPositionInfoModel::getOperationType));
        List<MbOrgInfo> mbOrgInfoList = mbOrgInfoLoader.selectByBusinessCode(corpCode);
        List<SyncPositionInfoModel> addPositionList = positionMap.get(PositionOperationEnum.ADD.getCode());
        String orgId = Conditional.ofEmptyAble(mbOrgInfoList)
                .map(list -> list.get(0))
                .map(MbOrgInfo::getOrgId)
                .orElseThrow(() -> new CorpBusinessException(OrganizationResponseCodeEnum.COMPANY_CODE_NOT_EXISTS));
        if (CollectionUtils.isNotEmpty(addPositionList)){
            List<MbPostInfo> mbPostInfoList = postService.findByNameAndOrgId(addPositionList.stream().map(SyncPositionInfoModel::getPositionName).collect(Collectors.toList()), orgId);
            Map<String, List<MbPostInfo>> existsMap = mbPostInfoList.stream()
                    .filter(post -> StringUtils.isNotBlank(post.getName()))
                    .collect(Collectors.groupingBy(MbPostInfo::getName));
            // 过滤掉数据库已经存在的职级
            addPositionList = addPositionList.stream()
                    .filter(addPosition -> CollectionUtils.isEmpty(existsMap.get(addPosition.getPositionName())))
                    .collect(Collectors.toList());
            postService.batchInsertPostInfo(convert(addPositionList, orgId));
        }

        List<SyncPositionInfoModel> deletePositionList = positionMap.get(PositionOperationEnum.DELETE.getCode());
        if (CollectionUtils.isNotEmpty(deletePositionList)){
            List<String>  needDeleteNameList = deletePositionList.stream().map(SyncPositionInfoModel::getPositionName).collect(Collectors.toList());
            postService.deleteByOrgIdAndName(orgId, needDeleteNameList);
        }
    }

    @Override
    public List<SyncOrgEmployeeReq.Employee> syncPosition4Employee(List<SyncOrgEmployeeReq.Employee> employeeList, Map<String, MbOrgInfo> businessCodeOrgMap) {
        try {
            /**
             * 1.先要求出公司id
             */
            Set<String> businessCodes = employeeList.stream().filter(p->StringUtils.isNotBlank(p.getBasicInfo().getPostName())).map(p -> p.getBasicInfo().getOrgId()).collect(Collectors.toSet());
            if(CollectionUtils.isEmpty(businessCodes)){
                return employeeList;
            }
            Map<String, String> orgCorpIdMap = getCorpIdByOrgId(businessCodes, businessCodeOrgMap);
            /**
             * 2.查职级信息
             */
            if(CollectionUtils.isEmpty(orgCorpIdMap.values())){
                log.error("找不到公司id,直接返回：{}", JsonUtils.toJsonString(businessCodes));
            }
            List<MbPostInfo> postInfoList = postService.listByOrgIds(new ArrayList<>(orgCorpIdMap.values()));
            Map<String, Long> postIdMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(postInfoList)) {
                postIdMap = postInfoList.stream().collect(Collectors.toMap(p -> p.getName() + ":" + p.getOrgId(), p -> p.getId(), (a, b) -> a));
            }
            log.info("部门职级信息：postIdMap={}",JsonUtils.toJsonString(postIdMap));
            /**
             * 3.为用户匹配职级id,postId
             */
            List<SyncOrgEmployeeReq.BasicInfo> noPostEmployeeList = new ArrayList<>();
            for (SyncOrgEmployeeReq.Employee employee : employeeList) {
                if(StringUtils.isBlank(employee.getBasicInfo().getPostName())){
                    continue;
                }
                SyncOrgEmployeeReq.BasicInfo basicInfo = employee.getBasicInfo();
                String corpId = orgCorpIdMap.get(employee.getBasicInfo().getOrgId());
                if (StringUtils.isBlank(corpId)) {
                    log.error("根据部门找不到对应的公司Id，uid={}, name={}, orgId={}", basicInfo.getUid(), basicInfo.getName(), basicInfo.getOrgId());
                    throw new CorpBusinessException(OrganizationResponseCodeEnum.CORP_NOT_FOUND_BY_ORG);
                }
                Long postId = postIdMap.get(basicInfo.getPostName() + ":" + corpId);
                log.info("职级postId={}, key={}", postId, (basicInfo.getPostName() + ":" + corpId));
                if (postId == null) {
                    noPostEmployeeList.add(basicInfo);
                } else {
                    basicInfo.setPostId(postId);
                }
            }
            if (CollectionUtils.isEmpty(noPostEmployeeList)) {
                return employeeList;
            }

            /**
             * 4.找不到职级则新增
             */
            List<MbPostInfo> newPOstInfoList = convert(noPostEmployeeList, orgCorpIdMap);
            postService.batchInsertPostInfo(newPOstInfoList);
            // 再次按公司查职级信息
            postInfoList = postService.listByOrgIds(newPOstInfoList.stream().map(p -> p.getOrgId()).collect(Collectors.toList()));
            if (CollectionUtils.isNotEmpty(postInfoList)) {
                postIdMap.putAll(postInfoList.stream().collect(Collectors.toMap(p -> p.getName() + ":" + p.getOrgId(), p -> p.getId(), (a, b) -> a)));
            }
            /**
             * 5.继续为用户匹配职级
             */
            for (SyncOrgEmployeeReq.BasicInfo basicInfo : noPostEmployeeList) {
                String corpId = orgCorpIdMap.get(basicInfo.getOrgId());
                if (StringUtils.isBlank(corpId)) {
                    log.error("根据部门找不到对应的公司Id，uid={}, name={}, orgId={}", basicInfo.getUid(), basicInfo.getName(), basicInfo.getOrgId());
                    throw new CorpBusinessException(OrganizationResponseCodeEnum.CORP_NOT_FOUND_BY_ORG);
                }
                basicInfo.setPostId(postIdMap.get(basicInfo.getPostName() + ":" + corpId));
            }
        } catch (Exception e){
            log.error("同步职级出错", e);
        }
        return employeeList;
    }

    /**
     * 求出部门对应的公司id
     * @param businessCodes
     * @return
     */
    private Map<String, String> getCorpIdByOrgId(Set<String> businessCodes, Map<String, MbOrgInfo> businessCodeOrgMap){
                // 求出部门对应的公司id
        Map<String, String> result = new HashMap<>();
        for(String businessCode:businessCodes){
            MbOrgInfo orgInfo = businessCodeOrgMap.get(businessCode);
            while (orgInfo!=null){
                // 找到公司id就保存并退出while
                if(OrgTypeEnum.C.getCode().equals(orgInfo.getOrgType())){
                    result.put(businessCode, orgInfo.getOrgId());
                    break;
                } else if(StringUtils.isNotBlank(orgInfo.getParentBusinessCode())){
                    orgInfo = businessCodeOrgMap.get(orgInfo.getParentBusinessCode());
                } else {
                    log.error("根据部门找不到对应的公司Id，orgId={}", businessCode);
                    throw new CorpBusinessException(OrganizationResponseCodeEnum.CORP_NOT_FOUND_BY_ORG);
                }
            }
        }
        log.info("部门对应的公司：{}", JsonUtils.toJsonString(result));
        return result;
    }

    private List<MbPostInfo> convert(List<SyncPositionInfoModel> addPositionList, String orgId){
        if (CollectionUtils.isEmpty(addPositionList)){
            return Collections.emptyList();
        }
        return addPositionList.stream().map(position -> {
            MbPostInfo mbPostInfo = new MbPostInfo();
            mbPostInfo.setCode(position.getPositionCode());
            mbPostInfo.setName(position.getPositionName());
            mbPostInfo.setDatachangeCreatetime(new Date());
            mbPostInfo.setDatachangeLasttime(new Date());
            mbPostInfo.setIsDeleted(false);
            mbPostInfo.setOrgId(orgId);
            return mbPostInfo;
        }).collect(Collectors.toList());
    }

    private List<MbPostInfo> convert(List<SyncOrgEmployeeReq.BasicInfo> employeeList, Map<String, String> orgCorpIdMap){
        Map<String, MbPostInfo> postInfoList = new HashMap<>();
        for(SyncOrgEmployeeReq.BasicInfo basicInfo:employeeList){
            String corpId = orgCorpIdMap.get(basicInfo.getOrgId());
            if(StringUtils.isBlank(corpId)){
                log.error("根据部门找不到对应的公司Id，orgId={}", basicInfo.getOrgId());
                throw new CorpBusinessException(OrganizationResponseCodeEnum.CORP_NOT_FOUND_BY_ORG);
            }
            // 职级去重
            String key = corpId+"_"+basicInfo.getPostName();
            if(postInfoList.containsKey(key)){
                continue;
            }
            MbPostInfo postInfo = new MbPostInfo();
            postInfoList.put(key, postInfo);
            postInfo.setCode(basicInfo.getPostCode());
            postInfo.setOrgId(corpId);
            postInfo.setName(basicInfo.getPostName());
            postInfo.setDatachangeCreatetime(new Date());
            postInfo.setDatachangeLasttime(new Date());
            postInfo.setIsDeleted(false);
        }
        return new ArrayList<>(postInfoList.values());
    }
}
